package com.apes.fn.server.workDesk.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.business.carAccident.modle.CarAccident;
import com.apes.fn.business.fixedLoss.modle.LossQuotation;
import com.apes.fn.controlling.vehicle.service.abstractVehicleinfo;
import com.apes.fn.crm.customerExpand.FnCustomerExpand;
import com.apes.fn.server.pickUpCar.model.PickUpCar;
import com.apes.fn.server.pickUpCar.repository.PickUpCarRepository;
import com.apes.fn.server.servicePlan.model.ServicePlan;
import com.apes.fn.server.servicePlan.repository.ServicePlanRepository;
import com.apes.fn.server.transferVehicle.model.InnerPickDeliveryUpCar;
import com.apes.fn.server.transferVehicle.model.InnerPickDeliveryUpCarItem;
import com.apes.fn.server.workDesk.model.VehicleControl;
import com.apes.fn.server.workDesk.model.VehicleControlItem;
import com.apes.fn.server.workDesk.repository.VehicleControlItemRepository;
import com.apes.fn.server.workDesk.repository.VehicleControlRepository;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.Model;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.express.FuncAlias;
import com.apes.framework.plugin.fsm.FsmFlowInstance;
import com.apes.framework.plugin.outbox.OutboxEventService;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.plugin.outbox.annotation.OutboxSubscriber;
import com.apes.framework.util.MapUtil;
import com.apes.scm.masterdata.frame.model.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 车辆信息服务
 *
 * @author lws
 * @create 2022-11-5 15:23
 **/

@Service
public class VehicleControlService extends abstractVehicleinfo {

    @Autowired
    private VehicleControlRepository vehicleControlRepository;
    @Autowired
    private ServicePlanRepository servicePlanRepository;
    @Autowired
    private PickUpCarRepository pickUpCarRepository;
    @Autowired
    private VehicleControlItemRepository vehicleControlItemRepository;

    @OutboxSubscriber(name = "车辆总控信息：接车单")
    public void subscribePickUpCar(PickUpCar pickUpCar) {
        createVehicleControl(pickUpCar.getDept(), pickUpCar.getFnCustomerExpand(), pickUpCar);
    }

    @OutboxSubscriber(name = "车辆总控信息：服务方案")
    public void subscribeServicePlan(ServicePlan servicePlan) {
        createVehicleControl(servicePlan.getBelongDept(), servicePlan.getFnCustomerExpand(), servicePlan);
    }

    @OutboxSubscriber(name = "车辆总控信息：定损报价 ")
    public void subscribeLossQuotation(LossQuotation lossQuotation) {
        createVehicleControl(lossQuotation.getFixedLossDept(), lossQuotation.getCustomerExpand(), lossQuotation);
    }

    @OutboxSubscriber(name = "车辆总控信息：内协交接车")
    public void subscribeInnerPickUpCar(InnerPickDeliveryUpCar pickUpCar) {
        createVehicleControl(pickUpCar.getBelongDept(), pickUpCar.getFnCustomerExpand(), pickUpCar);
        InnerPickDeliveryUpCarItem get = pickUpCar.getInnerPickDeliveryUpCarItemList().stream().filter(innerPickDeliveryUpCarItem -> innerPickDeliveryUpCarItem.getNodeDescription().equals("get")).findFirst().orElse(null);
        if (get==null)return;
        createVehicleControl(pickUpCar.getOtherSideDept(), pickUpCar.getFnCustomerExpand(), pickUpCar);
    }

    public Object flushFlowState(SimpleRequest request) {
        JSONObject jo = request.getJO();
        String deptId = "";
        String fnCustomerExpandId = "";
        if (jo.containsKey("servicePlanId")) {
            ServicePlan servicePlan = servicePlanRepository.findAll(JpaDsl.toCriteriaByEq("id", jo.getString("servicePlanId"))).stream().findFirst().orElse(null);
            if (servicePlan == null) throw new RuntimeException("查询不到该服务方案单！");
            deptId = servicePlan.getBelongDept().getId();
            fnCustomerExpandId = servicePlan.getFnCustomerExpand().getId();
        } else if (jo.containsKey("carNumber")) {
            List<PickUpCar> pickUpCars = pickUpCarRepository.findAll(JpaDsl.toCriteriaByEq("licenseNumber", jo.getString("carNumber")));
            pickUpCars.forEach(pickUpCar -> flushFlowStateByVehicleControl(pickUpCar.getDept().getId(), pickUpCar.getFnCustomerExpand().getId()));
        } else if (jo.containsKey("deptId") && jo.containsKey("fnCustomerExpandId")) {
            deptId = jo.getString("deptId");
            fnCustomerExpandId = jo.getString("fnCustomerExpandId");
        } else {
            Date startDate = jo.getDate("startDate");
            Date endDate = jo.getDate("endDate");
            List<VehicleControl> vehicleControls = vehicleControlRepository.findNotOver(startDate, endDate);
            vehicleControls.stream().forEach(vehicleControl -> SpringManager.getBean(OutboxEventService.class).sendSaveEvent(vehicleControl));
            return MapUtil.mapper("success", "true");
        }
        flushFlowStateByVehicleControl(deptId, fnCustomerExpandId);
        return MapUtil.mapper("success", "true");
    }

    /**
     * 刷新车辆总控状态，根据门店查询审核接车单
     *
     * @param request
     * @return
     */
    public Map flushFlowStateByDeptId(SimpleRequest request) {
        String deptId = request.getJO().getString("deptId");
        List<PickUpCar> pickUpCars = pickUpCarRepository.findAll(JpaDsl.toCriteriaByEq("dept.id", deptId, "state", "approve"));
        pickUpCars.stream().forEach(pickUpCar -> {
            flushFlowStateByVehicleControl(deptId, pickUpCar.getFnCustomerExpand().getId());
        });
        return MapUtil.mapper("success", "true");
    }

    private void flushFlowStateByVehicleControl(String deptId, String fnCustomerExpandId) {
        VehicleControl vehicleControl = vehicleControlRepository.findAll(JpaDsl.toCriteriaByEq("dept.id", deptId, "fnCustomerExpand.id", fnCustomerExpandId)).stream().findFirst().orElse(null);
        if (vehicleControl == null) return;
        SpringManager.getBean(OutboxEventService.class).sendSaveEvent(vehicleControl);
    }

    private void createVehicleControl(Dept dept, FnCustomerExpand fnCustomerExpand) {
        VehicleControl vehicleControl = vehicleControlRepository.findAll(JpaDsl.toCriteriaByEq("dept", dept, "fnCustomerExpand", fnCustomerExpand)).stream().findFirst().orElse(null);
        if (vehicleControl == null) {
            vehicleControl = new VehicleControl();
            vehicleControl.setDept(dept);
            vehicleControl.setFnCustomerExpand(fnCustomerExpand);
        }
        vehicleControlRepository.saveAndFlush(vehicleControl);
    }

    private void createVehicleControl(Dept dept, FnCustomerExpand fnCustomerExpand, Model model) {
        VehicleControl vehicleControl = vehicleControlRepository.findAll(JpaDsl.toCriteriaByEq("dept", dept, "fnCustomerExpand", fnCustomerExpand)).stream().findFirst().orElse(null);
        if (vehicleControl == null) {
            vehicleControl = new VehicleControl();
            vehicleControl.setDept(dept);
            vehicleControl.setFnCustomerExpand(fnCustomerExpand);
            vehicleControl.setState("ZK000751");
        }
        checkItemAndAdd(vehicleControl, model);
        vehicleControlRepository.saveAndFlush(vehicleControl);
    }

    private void checkItemAndAdd(VehicleControl vehicleControl, Model model) {
        List<VehicleControlItem> vehicleControlItems = vehicleControl.getVehicleControlItems();
        VehicleControlItem vehicleControlItem = vehicleControlItems.stream().filter(item -> model.getInnerBusinessKey().equals(item.getSourceOrder())).findFirst().orElse(new VehicleControlItem());
        if (model instanceof ServicePlan) {
            ServicePlan servicePlan = (ServicePlan) model;
            vehicleControlItem.setOrderCreateDate(servicePlan.getCreateDate());
            vehicleControlItem.setState(servicePlan.getState());
            vehicleControlItem.setSourceOrder(servicePlan.getId());
            vehicleControlItem.setSourceOrderType(servicePlan.getInnerBusinessType());
            vehicleControlItem.setOrderCreatePerson(servicePlan.getCreator());
        } else if (model instanceof PickUpCar) {
            PickUpCar pickUpCar = (PickUpCar) model;
            vehicleControlItem.setOrderCreateDate(pickUpCar.getCreateDate());
            vehicleControlItem.setState(pickUpCar.getState());
            vehicleControlItem.setSourceOrder(pickUpCar.getId());
            vehicleControlItem.setSourceOrderType(pickUpCar.getInnerBusinessType());
            vehicleControlItem.setOrderCreatePerson(pickUpCar.getCreator());
        } else if (model instanceof LossQuotation) {
            LossQuotation lossQuotation = (LossQuotation) model;
            vehicleControlItem.setOrderCreateDate(lossQuotation.getCreateDate());
            vehicleControlItem.setState(lossQuotation.getState());
            vehicleControlItem.setSourceOrder(lossQuotation.getId());
            vehicleControlItem.setSourceOrderType(lossQuotation.getInnerBusinessType());
            vehicleControlItem.setOrderCreatePerson(lossQuotation.getCreator());
        } else if (model instanceof InnerPickDeliveryUpCar) {
            InnerPickDeliveryUpCar innerPickDeliveryUpCar = (InnerPickDeliveryUpCar) model;
            if (innerPickDeliveryUpCar.getBelongDept().getId().equals(vehicleControl.getDept().getId())) {
                vehicleControlItem.setOrderCreateDate(innerPickDeliveryUpCar.getCreateDate());
                vehicleControlItem.setState(innerPickDeliveryUpCar.getState());
                vehicleControlItem.setSourceOrder(innerPickDeliveryUpCar.getId());
                vehicleControlItem.setSourceOrderType(innerPickDeliveryUpCar.getInnerBusinessType());
                vehicleControlItem.setOrderCreatePerson(innerPickDeliveryUpCar.getCreator());
            } else {
                vehicleControlItem.setState(innerPickDeliveryUpCar.getState());
                vehicleControlItem.setSourceOrder(innerPickDeliveryUpCar.getId());
                vehicleControlItem.setSourceOrderType(innerPickDeliveryUpCar.getInnerBusinessType());
                InnerPickDeliveryUpCarItem get = innerPickDeliveryUpCar.getInnerPickDeliveryUpCarItemList().stream().filter(innerPickDeliveryUpCarItem -> innerPickDeliveryUpCarItem.getNodeDescription().equals("get")).findFirst().orElse(null);
                if (get != null) {
                    vehicleControlItem.setOrderCreateDate(get.getCreateDate());
                    vehicleControlItem.setOrderCreatePerson(get.getCreator());
                }
            }

        }
        if (vehicleControlItem.getId() == null) {
            vehicleControlItem.setVehicleControl(vehicleControl);
            if (vehicleControl.getId()!=null)vehicleControlItemRepository.saveAndFlush(vehicleControlItem);
            vehicleControlItems.add(vehicleControlItem);
        }
    }

    public boolean isPickCar(String id) {
        VehicleControl vehicleControl = vehicleControlRepository.findOne(id);
        return carState(obtainCarData(vehicleControl.getDept().getId(), vehicleControl.getFnCustomerExpand().getId())); //接车状态
    }

//    @OutboxSubscriber(name = "订阅总控状态流,回写当前状态", condition = "fsmFlow.id == '000583'")
//    public void subscribeFsmFlowInstance(FsmFlowInstance fsmFlowInstance) {
//        String id = fsmFlowInstance.getCurrentState().getId();
//        VehicleControl vehicleControl = vehicleControlRepository.findOne(fsmFlowInstance.getBusinessKey());
//        vehicleControl.setState(id);
//        VehicleControl save = vehicleControlRepository.save(vehicleControl);
//    }

    @FuncAlias(name = "存在内协交车")
    public boolean haveInnerPickDeliveryUpCarByOut(String id) {
        VehicleControl vehicleControl = vehicleControlRepository.findOne(id);
        return carState(obtainInnerPickDelUpCarData(vehicleControl.getDept().getId(), vehicleControl.getFnCustomerExpand().getId())); //内协接车状态
    }

    @FuncAlias(name = "存在普通或内协接车")
    public boolean havePickUpCarOrInnerPickDeliveryUpCar(String id) {
        VehicleControl vehicleControl = vehicleControlRepository.findOne(id);
        Boolean flag = carState(obtainInnerPickDelUpCarDataByOtherSideDept(vehicleControl.getDept().getId(), vehicleControl.getFnCustomerExpand().getId())); //内协接车
        return isPickCar(id) || flag;
    }

    @FuncAlias(name = "无有效单据")
    public boolean haveNotValidDocuments(String id) {
        VehicleControl vehicleControl = vehicleControlRepository.findOne(id);
        JSONArray result = validDocuments(vehicleControl.getDept().getId(), vehicleControl.getFnCustomerExpand().getId());
        return result.size() <= 0;
    }

    @FuncAlias(name = "存在确认质检方案")
    public boolean havePlanByConfirmQualityTest(String id) {
        VehicleControl vehicleControl = vehicleControlRepository.findOne(id);
        JSONArray result = planByConfirmQualityTest(vehicleControl.getDept().getId(), vehicleControl.getFnCustomerExpand().getId());
        return result.size() > 0;
    }

    @FuncAlias(name = "方案均已记账")
    public boolean servicePlanByStateIsReceivables(String id) {
        VehicleControl vehicleControl = vehicleControlRepository.findOne(id);
        String deptId = vehicleControl.getDept().getId();
        String fnCustomerExpandId = vehicleControl.getFnCustomerExpand().getId();
        JSONArray validPlans = validPlans(deptId, fnCustomerExpandId);
        JSONArray receivablesPlans = receivablesPlans(deptId, fnCustomerExpandId);
        return validPlans.size() == receivablesPlans.size() && validPlans.size() > 0;
    }

    @FuncAlias(name = "存在未完结方案")
    public boolean hasNotEndServicePlan(String id) {
        VehicleControl vehicleControl = vehicleControlRepository.findOne(id);
        JSONArray jsonArray = hasNotEndServicePlan(vehicleControl.getDept().getId(), vehicleControl.getFnCustomerExpand().getId());
        return !jsonArray.isEmpty();
    }

    public int updateCarControlState(SimpleRequest request){
        int i = vehicleControlRepository.updateVehicleControlState();
        return i;
    }
    public int testControl(SimpleRequest request){
        JSONObject jo = request.getJO();
        ServicePlan servicePlan = servicePlanRepository.findOne(jo.getString("id"));
        createVehicleControl(servicePlan.getBelongDept(), servicePlan.getFnCustomerExpand(), servicePlan);
        return 1;
    }
}
